﻿/**
 * Peter
 * Created by: Peter Development Team
 *    http://peter.codeplex.com/
 * 
 * GNU General Public License version 2 (GPLv2)
 *    http://peter.codeplex.com/license
 *
 *  This code is provided on an AS IS basis, with no WARRANTIES,
 *  CONDITIONS or GUARANTEES of any kind.
 *
 **/

using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Input;
using ICSharpCode.NRefactory;
using Peter.Common.Interfaces;

namespace Peter.Common
{
   /// <summary>
   /// Requried methods and properties for a document content object.
   /// </summary>
   public abstract class PeterDocument : PeterDockItem, IPeterDocument
   {
      private RelayCommand m_OpenFolderCommand;
      private RelayCommand m_CopyPathCommand;
      private RelayCommand m_CloseCommand;
      private FileInfo m_FileInfo;

      /// <summary>
      /// Event that occurs when the text of the document changes.
      /// </summary>
      public event TextEventHandler TextChanged;

      /// <summary>
      /// Gets the close command.
      /// </summary>
      public ICommand CloseCommand
      {
         get { return this.m_CloseCommand ?? (this.m_CloseCommand = new RelayCommand (this.OnClose, this.CanClose)); }
      }

      /// <summary>
      /// Gets the close command.
      /// </summary>
      public ICommand CopyPathCommand
      {
         get { return this.m_CopyPathCommand ?? (this.m_CopyPathCommand = new RelayCommand (this.OnCopyPath)); }
      }

      /// <summary>
      /// Gets the open containing folder command.
      /// </summary>
      public ICommand OpenFolderCommand
      {
         get { return this.m_OpenFolderCommand ?? (this.m_OpenFolderCommand = new RelayCommand (this.OnOpenFolder)); }
      }

      /// <summary>
      /// Gets the text of the document.
      /// </summary>
      public abstract string Text { get; }

      /// <summary>
      /// Raises the text changed event.
      /// </summary>
      protected void RaiseTextChanged ()
      {
         if (this.TextChanged != null)
            this.TextChanged (this, new TextEventArgs (this.Text));
      }

      /// <summary>
      /// Opens the folder this document is located in.
      /// </summary>
      /// <param name="obj">Command parameter.</param>
      private void OnOpenFolder (object obj)
      {
         if (this.FileInfo != null)
         {
            var directoryInfo = this.FileInfo.Directory;
            if (directoryInfo != null)
            {
               string args = string.Format ("/Select, {0}", this.FileInfo.FullName);
               var pfi = new ProcessStartInfo ("Explorer.exe", args);
               Process.Start (pfi);
            }
         }
      }

      /// <summary>
      /// Copies the full path of this document to the clip board.
      /// </summary>
      /// <param name="obj">Command parameter.</param>
      private void OnCopyPath (object obj)
      {
         if (this.FileInfo != null)
         {
            if (obj.ToString () == "Full")
               Clipboard.SetText (this.FileInfo.FullName);
            else if (obj.ToString () == "Directory")
            {
               var directoryInfo = this.FileInfo.Directory;
               if (directoryInfo != null)
                  Clipboard.SetText (directoryInfo.FullName);
            }
            else
               Clipboard.SetText (this.FileInfo.Name);
         }
      }

      /// <summary>
      /// Checks to see if the item can close.
      /// </summary>
      /// <param name="obj">Command parameter.</param>
      /// <returns>True if able to close, otherwise false. Default is true.</returns>
      protected virtual bool CanClose (object obj)
      {
         return true;
      }

      /// <summary>
      /// Closes the current item.
      /// </summary>
      /// <param name="obj">Command parameter.</param>
      protected virtual void OnClose (object obj)
      {
         this.Peter.CloseDocument (this);
      }

      /// <summary>
      /// Gets the file of the document.
      /// </summary>
      public FileInfo FileInfo
      {
         get { return this.m_FileInfo; }
         set
         {
            this.m_FileInfo = value;
            this.RaisePropertyChanged ("FileInfo");
         }
      }

      /// <summary>
      /// Scrolls to the given offset.
      /// </summary>
      /// <param name="offset">Offset to scroll to.</param>
      public virtual void ScrollToOffset (int offset)
      {
      }

      /// <summary>
      /// Scrolls the document to the given location.
      /// </summary>
      /// <param name="location">Location to scroll to.</param>
      public virtual void ScrollToLocation (TextLocation location)
      {
         
      }
   }
}
